﻿using System;
using System.Collections.Generic;

using BizElements.Core;

namespace BizElements.BusinessLayer
{
    /// <summary>Strong domain/business object derived from BizElements entity classes that may be composed of other child entities and can provide metadata about itself.</summary>
    public interface IBusinessObject : IDataObject
    {
        #region Old IBusinessObject.

        /// <summary>
        /// Checks whether the actor has permissions to fetch the data requested.
        /// </summary>
        /// <param name="actor">Actor whose data-access permissions are to be checked.</param>
        /// <returns>Collection of permissions (broken rules) that the actor has failed.</returns>
        BusinessRuleCollection GrantFetch(IActor actor);

        /// <summary>
        /// Checks whether the actor has permissions to save the current object.
        /// </summary>
        /// <param name="actor">Actor whose data-access permissions are to be checked.</param>
        /// <returns>Collection of permissions (broken rules) that the actor has failed.</returns>
        BusinessRuleCollection GrantSave(IActor actor);

        /// <summary>
        /// Fetches a business object from the data-source.
        /// </summary>
        /// <param name="actionInitiator">Action initiator. This may be an application user, software module, 3rd party 
        /// application etc. which is initiating the fetch action. <b>Null</b> is not allowed.</param>
        /// <param name="detailLevel">Specifies the scope and the detail level of data (related entities) that is to be 
        /// fetched. Specifies the minimum required level. Method may fetch more than requested, but never less.</param>
        /// <param name="enforceSecurityChecks">Indicates whether the actor's permissions to fetch the requested data are
        /// checked. Set to <b>false</b> only if client is trusted and the security checks have been executed elsewhere.</param>
        /// <returns>True if business object was succesfully fetched; false otherwise.</returns>
        /// <exception cref="BrokenRuleException">The given actor failed the security checks. 
        /// Generated exception contains details about broken rules/permissions.</exception>
        bool Fetch(IActor actionInitiator, DataAccessScope detailLevel, bool enforceSecurityChecks);

        /// <summary>
        /// Persists a business object to data-source.
        /// </summary>
        /// <param name="actionInitiator">Action initiator. This may be an application user, software module, 3rd party 
        /// application etc. which is initiating the save action. <b>Null</b> is not allowed.</param>
        /// <param name="enforceSecurityChecks">Indicates whether the actor's permissions to save the current object are
        /// checked. Set to <b>false</b> only if client is trusted and the security checks have been executed elsewhere.</param>
        /// <exception cref="BrokenRuleException">The given actor failed the security checks. 
        /// Generated exception contains details about broken rules/permissions.</exception>
        void Save(IActor actionInitiator, bool enforceSecurityChecks);

        #endregion

        /// <summary>Gets object that provides generic interface for child entity collections and contains information about entity structure and security access permissions.</summary>
        /// <returns>Entity descriptor.</returns>
        IBusinessObjectDescriptor GetDescriptor();

        /// <summary>Ensures that all specified parent entities are fetched, ie. fetched.</summary>
        /// <param name="parentsToFetch">Relations.</param>
        void EnsureParents(DbRelation[] parentsToFetch);

        /// <summary>Checks whether the actor has permissions to deactivate/delete the current entity.</summary>
        /// <param name="actor">Actor whose data-access permissions are to be checked.</param>
        /// <returns>Collection of permissions (broken rules) that the actor has failed.</returns>
        BusinessRuleCollection GrantDeactivate(IActor actor);

        /// <summary>Deactivates/deletes the current entity if the provided actor has sufficient priviliges.</summary>
        /// <param name="actionInitiator">Action initiator. This may be an application user, software module, 3rd party application etc. which is initiating the save action. <b>Null</b> is not allowed.</param>
        /// <param name="enforceSecurityChecks">Indicates whether the actor's permissions to deactivate the current object are checked. Set to <b>false</b> only if client is trusted and the security checks have been executed elsewhere.</param>
        /// <exception cref="BrokenRuleException">Generated if the provided actor failed the security checks. Generated exception contains details about broken rules/permissions.</exception>
        void Deactivate(IActor actionInitiator, bool enforceSecurityChecks);

        /// <summary>Gets old version of entity that is currently saved in the database.</summary>
        /// <returns>Old/saved entity or <b>null</b> if the entity doesn't exist in the database yet.</returns>
        IEntity GetSavedVersion();

        /// <summary>Checks whether the current object instance is based on current/latest version of data. Used by optimistic offline locking scheme.</summary>
        /// <returns><b>true</b> if no concurrent data change has occured; otherwise <b>false</b></returns>
        bool IsCurrentVersion();
    }
}
